﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace QiHe.CodeGen.Aspx
{
    public partial class XmlNode
    {
        public Dictionary<string, string> Attributes;
        public List<XmlNode> ChildNodes;
        public string Value;
        public string Prefix;
        public string NodeName;
        public bool IsTransparent;
        public bool IsIndentChild;

        public XmlNode(string name)
        {
            NodeName = name;
            Attributes = new Dictionary<string, string>();
            ChildNodes = new List<XmlNode>();
            IsIndentChild = true;
        }

        public string GetMarkup()
        {
            StringBuilder text = new StringBuilder();
            StringWriter string_writer = new StringWriter(text);
            Output(string_writer, 4);
            return text.ToString();
        }

        public string GetHeader()
        {
            StringBuilder text = new StringBuilder();
            text.Append(NodeName);
            foreach (KeyValuePair<string, string> attr in Attributes)
            {
                text.AppendFormat(" {0}=\"{1}\"", attr.Key, attr.Value);
            }
            return text.ToString();
        }


        public void Output(TextWriter writer, int indent)
        {
            Output(writer, 0, indent);
        }

        public virtual void Output(TextWriter writer, int indentAccumulator, int indentWidth)
        {
            int indentwidth = IsIndentChild ? indentWidth : 0;
            if (IsTransparent)
            {
                foreach (XmlNode child in ChildNodes)
                {
                    child.Output(writer, indentAccumulator + indentwidth, indentWidth);
                }
            }
            else
            {
                writer.WriteLine();
                string blank = new string(' ', indentAccumulator);
                writer.Write(blank);
                writer.Write("<");
                string FullName = Prefix == null ? NodeName : Prefix + ":" + NodeName;
                writer.Write(FullName);
                foreach (KeyValuePair<string, string> attr in Attributes)
                {
                    if (attr.Value.Length > 40)
                    {
                        writer.WriteLine();
                        writer.Write(blank);
                        writer.Write("    ");
                    }
                    else
                    {
                        writer.Write(' ');
                    }
                    if (attr.Value.Contains("\""))
                    {
                        writer.Write("{0}=\'{1}\'", attr.Key, XmlEscape(attr.Value));
                    }
                    else
                    {
                        writer.Write("{0}=\"{1}\"", attr.Key, XmlEscape(attr.Value));
                    }
                }
                if (ChildNodes.Count == 0 && String.IsNullOrEmpty(Value))
                {
                    writer.Write(" />");
                }
                else
                {
                    writer.Write(">");
                    if (!String.IsNullOrEmpty(Value))
                    {
                        writer.Write(XmlEscape(Value));
                        foreach (XmlNode child in ChildNodes)
                        {
                            child.Output(writer, 0);
                        }
                    }
                    else
                    {
                        foreach (XmlNode child in ChildNodes)
                        {
                            child.Output(writer, indentAccumulator + indentwidth, indentWidth);
                        }
                        writer.WriteLine();
                        writer.Write(blank);
                    }
                    writer.Write("</{0}>", FullName);
                }
            }
        }

        private string XmlEscape(string Value)
        {
            return Value
                .Replace("&", "&amp;")
                .Replace("<", "&lt;")
                .Replace(">", "&gt;");
        }

        #region Attribute

        public string GetAttribute(string name)
        {
            if (Attributes.ContainsKey(name))
            {
                return Attributes[name];
            }
            return null;
        }

        public void SetAttribute(string name, string value)
        {
            Attributes[name] = value;
        }

        public void SetAttribute(string name, bool value)
        {
            Attributes[name] = value.ToString().ToLower();
        }

        public void SetAttribute(string name, object value)
        {
            if (value is bool)
            {
                Attributes[name] = value.ToString().ToLower();
            }
            else
            {
                this.SetAttribute(name, value.ToString());
            }
        }

        #endregion

        public void AddChild(XmlNode child)
        {
            this.ChildNodes.Add(child);
        }

        public void RemoveChild(XmlNode child)
        {
            this.ChildNodes.Remove(child);
        }
    }
}
